using AutoMapper;
using StudentManagement.Application.DTOs;
using StudentManagement.Domain.Entities;
using StudentManagement.Domain.Repositories;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System;

namespace StudentManagement.Application.Services
{
    public class UserService : IUserService
    {
        private readonly IUserRepository _userRepository;
        private readonly IRoleRepository _roleRepository;
        private readonly IMapper _mapper;
        private readonly IConfiguration _configuration;

        public UserService(IUserRepository userRepository, IRoleRepository roleRepository, IMapper mapper, IConfiguration configuration)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
            _mapper = mapper;
            _configuration = configuration;
        }

        public async Task<UserDTO> GetUserByIdAsync(int id)
        {
            var user = await _userRepository.GetByIdAsync(id);
            if (user == null)
            {
                throw new Exception("用户不存在");
            }

            var userDTO = _mapper.Map<UserDTO>(user);
            // 确保Roles集合被初始化
            if (userDTO.Roles == null)
            {
                userDTO.Roles = new List<string>();
            }
            
            // 获取用户角色信息
            if (user.UserRoles != null && user.UserRoles.Any())
            {
                foreach (var userRole in user.UserRoles)
                {
                    var role = await _roleRepository.GetByIdAsync(userRole.RoleId);
                    if (role != null && !userDTO.Roles.Contains(role.Name))
                    {
                        userDTO.Roles.Add(role.Name);
                    }
                }
            }
            return userDTO;
        }

        public async Task<UserDTO> GetUserByUsernameAsync(string username)
        {
            var user = await _userRepository.GetUserByUsernameAsync(username);
            if (user == null)
            {
                throw new Exception("用户不存在");
            }

            var userDTO = _mapper.Map<UserDTO>(user);
            // 确保Roles集合被初始化
            if (userDTO.Roles == null)
            {
                userDTO.Roles = new List<string>();
            }
            
            // 获取用户角色信息
            if (user.UserRoles != null && user.UserRoles.Any())
            {
                foreach (var userRole in user.UserRoles)
                {
                    var role = await _roleRepository.GetByIdAsync(userRole.RoleId);
                    if (role != null && !userDTO.Roles.Contains(role.Name))
                    {
                        userDTO.Roles.Add(role.Name);
                    }
                }
            }
            return userDTO;
        }

        public async Task<UserDTO> GetUserByEmailAsync(string email)
        {
            var user = await _userRepository.GetUserByEmailAsync(email);
            if (user == null)
            {
                throw new Exception("用户不存在");
            }

            var userDTO = _mapper.Map<UserDTO>(user);
            // 确保Roles集合被初始化
            if (userDTO.Roles == null)
            {
                userDTO.Roles = new List<string>();
            }
            
            // 获取用户角色信息
            if (user.UserRoles != null && user.UserRoles.Any())
            {
                foreach (var userRole in user.UserRoles)
                {
                    var role = await _roleRepository.GetByIdAsync(userRole.RoleId);
                    if (role != null && !userDTO.Roles.Contains(role.Name))
                    {
                        userDTO.Roles.Add(role.Name);
                    }
                }
            }
            return userDTO;
        }

        public async Task<IEnumerable<UserDTO>> GetAllUsersAsync()
        {
            var users = await _userRepository.GetAllAsync();
            var userDTOs = _mapper.Map<IEnumerable<UserDTO>>(users);

            // 初始化每个用户的角色列表
            foreach (var userDTO in userDTOs)
            {
                if (userDTO.Roles == null)
                {
                    userDTO.Roles = new List<string>();
                }
            }

            return userDTOs;
        }

        public async Task<IEnumerable<UserDTO>> GetUsersByRoleIdAsync(int roleId)
        {
            var users = await _userRepository.GetUsersByRoleIdAsync(roleId);
            var userDTOs = _mapper.Map<IEnumerable<UserDTO>>(users);

            // 获取角色名称
            var role = await _roleRepository.GetByIdAsync(roleId);
            var roleName = role?.Name;

            // 为每个用户添加角色信息
            foreach (var userDTO in userDTOs)
            {
                if (userDTO.Roles == null)
                {
                    userDTO.Roles = new List<string>();
                }
                
                if (!string.IsNullOrEmpty(roleName) && !userDTO.Roles.Contains(roleName))
                {
                    userDTO.Roles.Add(roleName);
                }
            }

            return userDTOs;
        }

        public async Task<UserDTO> CreateUserAsync(UserDTO userDTO)
        {
            // 检查用户名是否已存在
            if (await UsernameExistsAsync(userDTO.Username))
            {
                throw new System.Exception("用户名已存在");
            }

            // 检查邮箱是否已存在
            if (await EmailExistsAsync(userDTO.Email))
            {
                throw new System.Exception("邮箱已存在");
            }

            // 验证密码强度
            if (!IsPasswordStrong(userDTO.Password))
            {
                throw new System.Exception("密码强度不足，密码必须包含至少8个字符，包括大写字母、小写字母、数字和特殊字符");
            }

            // 加密密码
            userDTO.Password = HashPassword(userDTO.Password);

            var user = _mapper.Map<User>(userDTO);
            await _userRepository.AddAsync(user);

            return _mapper.Map<UserDTO>(user);
        }

        public async Task<UserDTO> UpdateUserAsync(int id, UserDTO userDTO)
        {
            var user = await _userRepository.GetByIdAsync(id);
            if (user == null)
            {
                throw new Exception("用户不存在");
            }

            // 检查用户名是否已被其他用户使用
            if (user.Username != userDTO.Username && await UsernameExistsAsync(userDTO.Username))
            {
                throw new System.Exception("用户名已存在");
            }

            // 检查邮箱是否已被其他用户使用
            if (user.Email != userDTO.Email && await EmailExistsAsync(userDTO.Email))
            {
                throw new System.Exception("邮箱已存在");
            }

            // 如果提供了新密码，则更新密码
            if (!string.IsNullOrEmpty(userDTO.Password))
            {
                // 验证密码强度
                if (!IsPasswordStrong(userDTO.Password))
                {
                    throw new System.Exception("密码强度不足，密码必须包含至少8个字符，包括大写字母、小写字母、数字和特殊字符");
                }

                // 加密密码
                userDTO.Password = HashPassword(userDTO.Password);
            }
            else
            {
                // 保持原密码（不需要在DTO中设置，因为我们不处理密码哈希）
            }

            // 手动更新User实体属性，而不是使用AutoMapper
            user.Username = userDTO.Username;
            user.Email = userDTO.Email;
            user.PhoneNumber = userDTO.PhoneNumber;
            user.FullName = userDTO.FullName;
            user.IsActive = userDTO.IsActive;
            
            // 如果提供了新密码，则更新密码
            if (!string.IsNullOrEmpty(userDTO.Password))
            {
                user.PasswordHash = HashPassword(userDTO.Password);
            }
            
            await _userRepository.UpdateAsync(user);

            return _mapper.Map<UserDTO>(user);
        }

        public async Task<bool> DeleteUserAsync(int id)
        {
            var user = await _userRepository.GetByIdAsync(id);
            if (user == null)
            {
                return false;
            }

            await _userRepository.DeleteAsync(id);
            return true;
        }

        public async Task<IEnumerable<UserDTO>> SearchUsersAsync(string keyword)
        {
            var users = await _userRepository.SearchUsersAsync(keyword);
            var userDTOs = _mapper.Map<IEnumerable<UserDTO>>(users);

            // 为每个用户添加角色信息
            foreach (var userDTO in userDTOs)
            {
                userDTO.Roles = new List<string>();
            }

            return userDTOs;
        }

        public async Task<bool> UsernameExistsAsync(string username)
        {
            return await _userRepository.UsernameExistsAsync(username);
        }

        public async Task<bool> EmailExistsAsync(string email)
        {
            return await _userRepository.EmailExistsAsync(email);
        }

        public async Task<UserDTO> LoginAsync(LoginDTO loginDTO)
        {
            var user = await _userRepository.GetUserByUsernameAsync(loginDTO.Username);
            if (user == null || !VerifyPassword(loginDTO.Password, user.PasswordHash))
            {
                throw new Exception("用户名或密码错误");
            }

            var userDTO = _mapper.Map<UserDTO>(user);
            // 确保Roles集合被初始化
            if (userDTO.Roles == null)
            {
                userDTO.Roles = new List<string>();
            }
            
            // 获取用户角色信息
            if (user.UserRoles != null && user.UserRoles.Any())
            {
                foreach (var userRole in user.UserRoles)
                {
                    var role = await _roleRepository.GetByIdAsync(userRole.RoleId);
                    if (role != null && !userDTO.Roles.Contains(role.Name))
                    {
                        userDTO.Roles.Add(role.Name);
                    }
                }
            }

            return userDTO;
        }

        public async Task<UserDTO> RegisterAsync(RegisterDTO registerDTO)
        {
            // 检查用户名是否已存在
            if (await UsernameExistsAsync(registerDTO.Username))
            {
                throw new System.Exception("用户名已存在");
            }

            // 检查邮箱是否已存在
            if (await EmailExistsAsync(registerDTO.Email))
            {
                throw new System.Exception("邮箱已存在");
            }

            // 验证密码是否匹配
            if (registerDTO.Password != registerDTO.ConfirmPassword)
            {
                throw new System.Exception("两次输入的密码不一致");
            }

            // 验证密码强度
            if (!IsPasswordStrong(registerDTO.Password))
            {
                throw new System.Exception("密码强度不足，密码必须包含至少8个字符，包括大写字母、小写字母、数字和特殊字符");
            }

            // 创建用户DTO
            var userDTO = new UserDTO
            {
                Username = registerDTO.Username,
                Email = registerDTO.Email,
                PhoneNumber = registerDTO.PhoneNumber,
                FullName = registerDTO.FullName,
                // 注意：这里我们直接传递密码，因为CreateUserAsync方法会处理密码哈希
                Password = registerDTO.Password,
                IsActive = true,
                CreatedAt = DateTime.Now,
                Roles = new List<string>() { "Student" } // 默认学生角色
            };

            return await CreateUserAsync(userDTO);
        }

        // 密码强度验证
        private bool IsPasswordStrong(string password)
        {
            // 密码必须包含至少8个字符，包括大写字母、小写字母、数字和特殊字符
            var passwordRegex = new Regex(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$");
            return passwordRegex.IsMatch(password);
        }

        // 密码加密
        private string HashPassword(string password)
        {
            // 在实际应用中，应该使用更安全的密码哈希算法，如BCrypt或PBKDF2
            // 这里为了简单起见，使用了一个简单的哈希方法
            return BCrypt.Net.BCrypt.HashPassword(password);
        }

        // 密码验证
        private bool VerifyPassword(string password, string hashedPassword)
        {
            // 在实际应用中，应该使用与哈希方法对应的验证方法
            return BCrypt.Net.BCrypt.Verify(password, hashedPassword);
        }

        // 生成JWT令牌
        private string GenerateJwtToken(User user)
        {
            var jwtSettings = _configuration.GetSection("JwtSettings");
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["SecretKey"] ?? string.Empty));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            var claims = new[]
            {
                new Claim(JwtRegisteredClaimNames.Sub, user.Username),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                new Claim(ClaimTypes.Name, user.Username)
            };

            // 添加角色声明
            if (user.UserRoles != null && user.UserRoles.Any())
            {
                foreach (var userRole in user.UserRoles)
                {
                    var role = _roleRepository.GetByIdAsync(userRole.RoleId).Result;
                    if (role != null)
                    {
                        claims = claims.Concat(new[] { new Claim(ClaimTypes.Role, role.Name) }).ToArray();
                    }
                }
            }

            var token = new JwtSecurityToken(
                issuer: jwtSettings["Issuer"],
                audience: jwtSettings["Audience"],
                claims: claims,
                expires: DateTime.Now.AddHours(Convert.ToDouble(jwtSettings["ExpirationHours"])),
                signingCredentials: credentials);

            return new JwtSecurityTokenHandler().WriteToken(token);
        }

        // 验证用户凭据并返回用户信息和角色
        public async Task<(bool isValid, int userId, string username, List<string> roles)> ValidateUserAsync(string username, string password)
        {
            var user = await _userRepository.GetUserByUsernameAsync(username);
            if (user == null || !VerifyPassword(password, user.PasswordHash))
            {
                return (false, 0, string.Empty, new List<string>());
            }

            var roles = new List<string>();
            if (user.UserRoles != null && user.UserRoles.Any())
            {
                foreach (var userRole in user.UserRoles)
                {
                    var role = await _roleRepository.GetByIdAsync(userRole.RoleId);
                    if (role != null && !roles.Contains(role.Name))
                    {
                        roles.Add(role.Name);
                    }
                }
            }

            return (true, user.Id, user.Username, roles);
        }

        // 获取指定用户ID的角色列表
        public async Task<List<string>> GetUserRolesAsync(int userId)
        {
            var user = await _userRepository.GetByIdAsync(userId);
            if (user == null || user.UserRoles == null || !user.UserRoles.Any())
            {
                return new List<string>();
            }

            var roles = new List<string>();
            foreach (var userRole in user.UserRoles)
            {
                var role = await _roleRepository.GetByIdAsync(userRole.RoleId);
                if (role != null && !roles.Contains(role.Name))
                {
                    roles.Add(role.Name);
                }
            }

            return roles;
        }
    }
}